#!/usr/bin/python
# -*- coding: UTF-8 -*-
import time
import sys
import numpy as np

from os.path import join
import fileinput
# 2022、6、1 更新：自适应的cpu频率和操作数
ROOT = "../evaluation/"
NUM_ITER = 50

# 获取cpu频率，因为计时采用的是CPU周期
def get_cpu_ghz():
    for line in fileinput.FileInput('/proc/cpuinfo'):
        if 'model name' in line:
            value = line.split('@ ')[1][:-1]
            digit = value[:-3]
            tag = value[-3:]
            if tag == "GHz":
                return float(digit)
            elif tag == "MHz":
                return float(digit) / 1000.0
            else:
                raise ValueError

cpu_freq_ghz = get_cpu_ghz()
S2US_FCTR = 1000000
K_FCTR = 1000
G_FCTR = 1000 * 1000 * 1000


# 计算操作延迟和秒千吞吐率
def circle_to_latencyInUs(num_circles, num_ops):
    """微秒延迟"""
    if num_ops:
        return (num_circles * 2.6 / np.array(num_ops) / (cpu_freq_ghz * G_FCTR)) * S2US_FCTR
    else:
        return -1


def kop_in_s(num_circles, num_ops):
    """秒千吞吐率"""
    return (1 / ((num_circles * 2.6 / num_ops) / (cpu_freq_ghz * G_FCTR))) / K_FCTR


def get_timer_means(filename):
    timer_all = -1
    timer_read = -1
    timer_write = -1
    with open(filename, 'r') as f:
        lines = f.readlines()
    for line in lines:
        if line.startswith("Timer 13 MEAN"):
            timer_all = int(line.split(",")[0].split(":")[1])
        elif line.startswith("Timer 4 MEAN"):
            timer_read = int(line.split(",")[0].split(":")[1])
        elif line.startswith("Timer 10 MEAN"):
            timer_write = int(line.split(",")[0].split(":")[1])
    return [timer_all, timer_read, timer_write]


def get_numOps_from_perfLog(filename):
    with open(filename, 'r') as f:
        lines = f.readlines()
    all_nums = []
    read_nums = []
    write_nums = []
    read_ratios = []
    for line in lines:
        if "period" in line:
            all_num = int(line.split('-')[3])
            read_num = int(line.split('-')[5])
            write_num = int(line.split('-')[7])
            read_ratio = float((read_num+0.0) / all_num)

            all_nums.append(all_num)
            read_nums.append(read_num)
            write_nums.append(write_num)
            read_ratios.append(read_ratio)

    assert (len(read_nums) == len(write_nums))
    d = dict({'all_nums': all_nums, 'read_nums': read_nums, 'write_nums': write_nums, 'read_ratios': read_ratios})
    return d


def get_mean(lyst):
    return np.array(lyst).mean()


def dataset(d):
    localtime = time.asctime(time.localtime(time.time()))
    print("Dataset Distibution, collected at %s\n" % localtime)
    # datasets = ["linear_64M", "linear_64Mseg1", "linear_64Mseg10", "norm_64M", "idf_all"]
    # datasets = ["idf_575_valid", "idf_95_valid", "idf_175_valid", "idf_351_valid"]
    print("dataset_types", d)
    dataname = d.split('_')[0]
    operation = '_'.join(d.split('_')[1:])
    [baseline_mean_all, baseline_mean_read, baseline_mean_write] = get_timer_means(join(ROOT, "{}_baseline.txt".format(d)))
    [llsm_mean_all, llsm_mean_read, llsm_mean_write] = get_timer_means(join(ROOT, "{}_llsm.txt".format(d)))

    dataname = d.split('_')[0]
    num_ops = get_numOps_from_perfLog("../evaluation/" + dataname + '_' + operation + '_baseline.txt')
    op_type = d.split('_')[-2]
    if op_type == 'allGet':
        num_ops['read_nums'] = num_ops['all_nums']
        num_ops['write_nums'] = [0]*NUM_ITER
    if op_type == 'allPut':
        num_ops['write_nums'] = num_ops['all_nums']
        num_ops['read_nums'] = [0]*NUM_ITER
    if not baseline_mean_all == -1:
        num_ops_mean_all = get_mean(num_ops['all_nums'])
        num_ops_mean_read = get_mean(num_ops['read_nums'])
        num_ops_mean_write = get_mean(num_ops['write_nums'])

        print("{} baseline_mean_all latency: {:.2f} microseconds".format(d, circle_to_latencyInUs(baseline_mean_all, num_ops_mean_all)))
        print("{} llsm_mean_all latency: {:.2f} microseconds".format(d, circle_to_latencyInUs(llsm_mean_all, num_ops_mean_all)))

        print("{} baseline_mean_read latency: {:.2f} microseconds".format(d, circle_to_latencyInUs(baseline_mean_read, num_ops_mean_read)))
        print("{} llsm_mean_read latency: {:.2f} microseconds".format(d, circle_to_latencyInUs(llsm_mean_read, num_ops_mean_read)))

        print("{} baseline_mean_write latency: {:.2f} microseconds".format(d, circle_to_latencyInUs(baseline_mean_write, num_ops_mean_write)))
        print("{} llsm_mean_write latency: {:.2f} microseconds".format(d, circle_to_latencyInUs(llsm_mean_write, num_ops_mean_write)))
        print("")


def main():
    expr = int(sys.argv[1])
    if len(sys.argv) != 2 and len(sys.argv) != 3:
        print("Usage: prog expr_num \\in [1-5]")
    elif len(sys.argv) == 3:
        dataset_type = sys.argv[2]

    if expr == 1:
        dataset(dataset_type)


if __name__ == '__main__':
    main()
